package com.ease.map.common.util {
    import com.ease.map.common.enum.GeoTypeEnum;
    import com.ease.map.geometry.IGeometry;
    import com.ease.map.geometry.PointGeometry;
    import com.ease.map.geometry.PolygonGeometry;
    import com.ease.map.geometry.PolylineGeometry;
    import com.ease.map.geometry.basetype.Location;
    import com.ease.map.handler.feature.draw.snap.AddVertexInfo;
    import com.ease.map.style.PolylineStyle;
    
    import mx.collections.ArrayCollection;

    /**
     * 几何计算类
     */
    public class GMath {
        /**得到点在线上的垂点(该点可能不在线上)
         * @x		点的X坐标
         * @y		点的y坐标
         * @x1		线的起点X坐标
         * @y1		线的起点Y坐标
         * @x2		线的终点x坐标
         * @y2		线的终点y坐标
         */
        private static function dotLineIntersection(x:Number, y:Number, x1:Number, y1:Number, x2:Number, y2:Number):Location {
            var loc:Location;
            if (Math.abs(x1 - x2) < 0.001) {
                return new Location(y, x1);
            }
            if (Math.abs(y1 - y2) < 0.001) {
                return new Location(y1, x);
            }

            var tg:Number;
            var newx:Number, newy:Number;
            tg = -1 / ((y2 - y1) / (x2 - x1));
            newx = (x2 * (x * tg - y + y1) + x1 * (x * -tg + y - y2)) / (tg * (x2 - x1) + y1 - y2);
            newy = tg * newx - tg * x + y;
            return loc = new Location(newy, newx);

        }

        /**
         *已知未知点到线上A端的距离，求点位置
         * @p1 线的A端点
         * @p2  线的B端点
         * @distance 点到A的距离
         * */
        public static function getPointByDistanceInLine(p1:PointGeometry, p2:PointGeometry, distance:Number):PointGeometry {
            var y:Number;
            var x:Number;
            y = ((p2.y - p1.y) * distance) / (distance + TwoPointDistance(p1, p2));
            x = Math.sqrt(distance * distance - y * y);
            var tempPoint:PointGeometry = new PointGeometry(p1.x + x, p1.y + y);
            var point:PointGeometry = new PointGeometry();
            NearestPointInLine(tempPoint, p1.x, p1.y, p2.x, p2.y, point);
            return point;
        }

        /**得到地理上 线段与水平的夹角
         * @x1		线的起点X坐标
         * @y1		线的起点Y坐标
         * @x2		线的终点x坐标
         * @y2		线的终点y坐标
         * @return 角度范围[0-360)
         */
        public static function lineAngle(x1:Number, y1:Number, x2:Number, y2:Number):Number {
            var ang:Number = 0;
            if (Math.abs(x1 - x2) < 0.000001) {
                if (y1 < y2) {
                    ang = 90;
                }
                else if (y1 > y2) {
                    ang = -90;
                }
            }
            else {
                if (x1 > x2) {
                    ang = Math.atan((y2 - y1) / (x2 - x1)) / Math.PI * 180 + 180;
                }
                else if (x2 > x1) {
                    ang = Math.atan((y2 - y1) / (x2 - x1)) / Math.PI * 180;
                }
            }

            if (ang < 0) {
                ang = ang + 360;
            }

            return ang;
        }

        /**得到点在线上的最近点
         * @x 点的X坐标
         * @y 点的y坐标
         * @x1 线的起点X坐标
         * @y1 线的起点Y坐标
         * @x2 线的终点x坐标
         * @y2 线的终点y坐标
         * @rtPoint为返回的最近点
         */
        private static function NearestPointInLine(point:PointGeometry, x1:Number, y1:Number, x2:Number, y2:Number, rtPoint:PointGeometry):Boolean {
            var bIsSnapLine:Boolean = true; //最近点是线上点还是两个端点之一
            var newx:Number = 0.0;
            var newy:Number = 0.0;
            if (Math.abs(x1 - x2) < 0.0000001) {
                newx = x1;
                newy = point.y;
            }
            else if (Math.abs(y1 - y2) < 0.0000001) {
                newx = point.x;
                newy = y1;
            }
            else {
                var tg:Number = 0.0;
                tg = -1 / ((y2 - y1) / (x2 - x1));
                newx = (x2 * (point.x * tg - point.y + y1) + x1 * (point.x * -tg + point.y - y2)) / (tg * (x2 - x1) + y1 - y2);
                newy = tg * newx - tg * point.x + point.y;

            }

            var d:Number = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); //线段长度
            var d1:Number = Math.sqrt((newx - x1) * (newx - x1) + (newy - y1) * (newy - y1)); //点到线段第一个点的距离
            var d2:Number = Math.sqrt((newx - x2) * (newx - x2) + (newy - y2) * (newy - y2)); //点到线段第二个点的距离

            if (d1 > d || d2 > d) //证明最近点是线的两个端点
            {
                bIsSnapLine = false; //捕捉点是线的两个端点之一
                if (d1 < d2) {
                    newx = x1;
                    newy = y1;
                }
                else {
                    newx = x2;
                    newy = y2;
                }
            }
            rtPoint.x = newx;
            rtPoint.y = newy;
            return bIsSnapLine;
        }

        /**
         * 计算面积
         */
        public static function CalcLArea(locationArray:ArrayCollection, llPoint:Location):Number {
            if (locationArray.length > 0 && llPoint) {
                var areaTotal:Number = 0.0;
                var pt:Location = new Location(0, 0);

                for (var i:int = 0; i < locationArray.length; i++) {
                    if (i < (locationArray.length - 1)) {
                        areaTotal = areaTotal + triangleArea(pt, locationArray.getItemAt(i) as Location, locationArray.getItemAt(i + 1) as Location);
                    }
                    else {
                        areaTotal = areaTotal + triangleArea(pt, locationArray.getItemAt(i) as Location, llPoint);
                    }
                }
                //加上动态点和第一个点组成的面积
                areaTotal = areaTotal + triangleArea(pt, llPoint, locationArray.getItemAt(0) as Location);

                return Math.abs(areaTotal) / 2;
            }
            return 0;
        }

        /**
         *计算3个点组成的面积
         */
        private static function triangleArea(pt1:Location, pt2:Location, pt3:Location):Number {
            return (pt1.x - pt3.x) * (pt2.y - pt3.y) - (pt2.x - pt3.x) * (pt1.y - pt3.y);
        }

        /**
         * 计算多边形质心
         * 公式：
         * X = SUM[(Xi + Xi+1) * (Xi * Yi+1 - Xi+1 * Yi)] / 6 / A
         * Y = SUM[(Yi + Yi+1) * (Xi * Yi+1 - Xi+1 * Yi)] / 6 / A
         */
        public static function polygonCentroid(polygon:PolygonGeometry):Location {
            var X:Number = 0;
            var Y:Number = 0;
            var area:Number = 0;
            var pointarray:ArrayCollection = new ArrayCollection();
            var tmp:Number;
            for (var i:int = 0; i < polygon.lineList.length; i++) {
                if (polygon.lineList.getItemAt(i) is PolylineGeometry) {
                    var polyline:PolylineGeometry = polygon.lineList.getItemAt(i) as PolylineGeometry;
                    for (var j:int = 0; j < polyline.pointList.length; j++) {
                        pointarray.addItem(new Location(polyline.pointList.getItemAt(j).x, polyline.pointList.getItemAt(j).y));
                    }
                }
            }

            area = CalcLArea(pointarray, pointarray.getItemAt(0) as Location);
            for (i = 0; i < pointarray.length - 1; i++) {
                tmp = pointarray.getItemAt(i).x * pointarray.getItemAt(i + 1).y - pointarray.getItemAt(i + 1).x * pointarray.getItemAt(i).y;
                X = X + (pointarray.getItemAt(i).x + pointarray.getItemAt(i + 1).x) * tmp;
                Y = Y + (pointarray.getItemAt(i).y + pointarray.getItemAt(i + 1).y) * tmp;
            }
            X = Math.abs(X / 6 / area); //有点问题，顺时针画的多边形会计算出负数
            Y = Math.abs(Y / 6 / area);
            return new Location(X, Y);
        }

        /**
         *
         * 计算两个点之间的距离
         * */
        public static function TwoPointDistance(point1:PointGeometry, point2:PointGeometry):Number {
            return Math.sqrt((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y));
        }

        /**
         * 计算两个location形式点的距离
         * */
        public static function TwoLocDistance(point1:Location, point2:Location):Number {
            return Math.sqrt((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y));
        }

        /**线的长度
         * @x1		线的起点X坐标
         * @y1		线的起点Y坐标
         * @x2		线的终点x坐标
         * @y2		线的终点y坐标
         */
        public static function lineLength(x1:Number, y1:Number, x2:Number, y2:Number):Number {
            return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        }

        /**点到线的最近距离
           @x 		点的x坐标
           @y 		点的y坐标
           @x0 	线的起点x坐标
           @y0 	线的起点y坐标
           @x1 	线的终点x坐标
           @y1 	线的终点y坐标
           @overLine true表示离线的最近点距离，false表示垂直距离
         */
        public static function dotLineLength(x:Number, y:Number, x0:Number, y0:Number, x1:Number, y1:Number, overLine:Boolean = false):Number {
            var loc:Location = dotLineIntersection(x, y, x0, y0, x1, y1);
            if (overLine && !(loc.x >= Math.min(x0, x1) && loc.x <= Math.max(x0, x1) && loc.y >= Math.min(y0, y1) && loc.y <= Math.max(y0, y1))) {
                var l1:Number = lineLength(x, y, x0, y0), l2:Number = lineLength(x, y, x1, y1);
                return l1 > l2 ? l2 : l1;


            }
            else {
                var a:Number = y0 - y1, b:Number = x1 - x0, c:Number = x0 * y1 - y0 * x1;
                return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
            }

        }


        /**线的斜率
         * @x1		线的起点X坐标
         * @y1		线的起点Y坐标
         * @x2		线的终点x坐标
         * @y2		线的终点y坐标
         */
        public static function lineSlope(x1:Number, y1:Number, x2:Number, y2:Number):Number {
            if (x2 == x1)
                return 1;
            else
                return (y2 - y1) / (x2 - x1);
        }

        /**
         *  查找点在面对象中的最近点
         * @param point 查找点
         * @param polygonGeo 查找面
         * @vertexInfo  查找面离查找点最近的点
         */
        public static function NearestPntInPolygonGeometry(point:PointGeometry, polygon:PolygonGeometry, vertexInfo:AddVertexInfo):void {
            var subGeo:IGeometry = null;
            var polylineGeo:PolylineGeometry = null;

            for (var i:int = 0; i < polygon.lineList.length; i++) {
                subGeo = IGeometry(polygon.lineList.getItemAt(i));

                if (subGeo.getGeometryType() == GeoTypeEnum.POLYLINEGEOMETRY) {
                    polylineGeo = subGeo as PolylineGeometry;

                    NearestPntInPolylineGeometry(point, polylineGeo, vertexInfo);
                }
            }
        }

        /**
         *查找点离多义线PolylineGeometry最近点
         * @param point 查找点
         * @param polyline 查找多义线
         * @param vertexInfo 找到的最近点
         *
         */
        public static function NearestPntInPolylineGeometry(point:PointGeometry, polyline:PolylineGeometry, vertexInfo:AddVertexInfo):void {

            var current_Point:PointGeometry = new PointGeometry();
            var distance:Number = -1;

            for (var i:int = 0; i < (polyline.pointList.length - 1); i++) {
                //找到离此线段最近的点，算出距离
                NearestPointInLine(point, PointGeometry(polyline.pointList.getItemAt(i)).x, PointGeometry(polyline.pointList.getItemAt(i)).y, PointGeometry(polyline.pointList.getItemAt(i + 1)).x, PointGeometry(polyline.pointList.getItemAt(i + 1)).y, current_Point);

                //计算长度
                distance = TwoPointDistance(point, current_Point);
                if (vertexInfo.distance > distance) {
                    vertexInfo.distance = distance;
                    vertexInfo.pointIndex = i;
                    vertexInfo.pointGeometry.x = current_Point.x;
                    vertexInfo.pointGeometry.y = current_Point.y;
                    vertexInfo.parentGeo = polyline;
                }
            }
        }

        /**
         * 找到点在多段线上的最近点，然后插入这个点到线上
         * @param point 		点的X坐标
         * @param polylineGeo	点的Y坐标
         * @polylineGeo	线对象
         */
        public static function NearestPntInPolyline(point:PointGeometry, polylineGeo:PolylineGeometry, rtPoint:PointGeometry):Boolean {
            var bIsSnapLine:Boolean = true;
            var bReturenBooL:Boolean = true;

            var current_Point:PointGeometry = new PointGeometry();

            var current_distance:Number = -1;
            var distance:Number = -1;

            for (var i:int = 0; i < (polylineGeo.pointList.length - 1); i++) {
                bReturenBooL = NearestPointInLine(point, PointGeometry(polylineGeo.pointList.getItemAt(i)).x, PointGeometry(polylineGeo.pointList.getItemAt(i)).y, PointGeometry(polylineGeo.pointList.getItemAt(i + 1)).x, PointGeometry(polylineGeo.pointList.getItemAt(i + 1)).y, current_Point);

                //计算长度
                //distance=Math.sqrt((x - current_Point.x) * (x - current_Point.x) + (y - current_Point.y) * (y - current_Point.y));
                distance = TwoPointDistance(point, current_Point);
                if (i == 0) {
                    current_distance = distance;
                    bIsSnapLine = bReturenBooL;
                    rtPoint.x = current_Point.x;
                    rtPoint.y = current_Point.y;
                }
                else {
                    if (current_distance > distance) {
                        current_distance = distance;
                        bIsSnapLine = bReturenBooL;
                        rtPoint.x = current_Point.x;
                        rtPoint.y = current_Point.y;
                    }
                }
            }
            return bIsSnapLine;
        }

        /**找到点在多段线上的最近点，然后插入这个点到线上
         * @x		点的X坐标
         * @y		点的Y坐标
         * @linepoints	线的所有折点
         */
        public static function InsertPointToLine(x:Number, y:Number, newpoint:PointGeometry, linepoints:ArrayCollection):int {

            var loc1:PointGeometry, loc2:PointGeometry;
            var prevlen:Number = 500000, index:Number;

            for (var i:Number = 0; i < linepoints.length - 1; i++) {
                loc1 = linepoints.getItemAt(i) as PointGeometry;
                loc2 = linepoints.getItemAt(i + 1) as PointGeometry;

                var len:Number = dotLineLength(x, y, loc1.x, loc1.y, loc2.x, loc2.y, true);
                if (len < prevlen) {
                    index = i;
                    prevlen = len;
                }
            }
            loc1 = linepoints.getItemAt(index) as PointGeometry;
            loc2 = linepoints.getItemAt(index + 1) as PointGeometry;
            var insertloc:Location = dotLineIntersection(x, y, loc1.x, loc1.y, loc2.x, loc2.y)

            newpoint.x = insertloc.x;
            newpoint.y = insertloc.y;

            linepoints.addItemAt(newpoint, index + 1);

            return index + 1;
        }


        /*
         *    判断点(x, y)是否在线段(x1, y1) ----- (x2, y2)的左边
         *   (x1, y1)
         *     \
         *		 \   . (x, y)			<----------- true
         *       \
         *      (x2, y2)
         */
        public static function leftSide(x1:Number, y1:Number, x2:Number, y2:Number, x:Number, y:Number):Boolean {
            return (y - y1) * (x2 - x1) > (x - x1) * (y2 - y1);
        }

        /*
         *   判断两条线段是否有交点
         *	@param线段a：(xa1, ya1) ----- (xa2, ya2)
         *	@param线段b：(xb1, yb1) ----- (xb2, yb2)
         *  @param  delta 容差
         */
        public static function lineCross(xa1:Number, ya1:Number, xa2:Number, ya2:Number, xb1:Number, yb1:Number, xb2:Number, yb2:Number, delta:Number = 0.00001):Boolean {
            //端点在线上相交
            if (pointOnLine(xb1, yb1, xa1, ya1, xa2, ya2, delta) || pointOnLine(xb2, yb2, xa1, ya1, xa2, ya2, delta) || pointOnLine(xa2, ya2, xb1, yb1, xb2, yb2, delta) || pointOnLine(xa1, ya1, xb1, yb1, xb2, yb2, delta))
                return true;

            return leftSide(xa1, ya1, xa2, ya2, xb1, yb1) != leftSide(xa1, ya1, xa2, ya2, xb2, yb2) && leftSide(xb1, yb1, xb2, yb2, xa1, ya1) != leftSide(xb1, yb1, xb2, yb2, xa2, ya2);
        }

        /*
         * 点是否在线上
         *	线段：(x1, y1) ----- (x2, y2)
         *  @param (x, y) 被判断的点
         *  @param  delta 容差
         */
        public static function pointOnLine(x:Number, y:Number, x1:Number, y1:Number, x2:Number, y2:Number, delta:Number = 0.00001):Boolean {
            var a:Number = lineLength(x1, y1, x, y);
            if (a < delta)
                return true;
            var b:Number = lineLength(x2, y2, x, y);
            if (b < delta)
                return true;
            var c:Number = lineLength(x1, y1, x2, y2);

            if (Math.abs(a + b - c) < delta) {
                return true;
            }

            return false;
        }

        /**
         *
         * 判断点是否在线段上
         * @param point 待判断的点
         * @param point1 线段端点A
         * @param point2 线段端点B
         * */
        public static function isPointInLine(point:PointGeometry, point1:PointGeometry, point2:PointGeometry):Boolean {
            var a:Number = TwoPointDistance(point1, point);
            if (a < 0.0000001) {
                return true;
            }
            var b:Number = TwoPointDistance(point, point2);
            if (b < 0.0000001) {
                return true;
            }
            var c:Number = TwoPointDistance(point1, point2);
            if (Math.abs(a + b - c) < 0.0000001) {
                return true;
            }
            return false;
        }


		/**点是否在矩形内
		 * @x		点的X坐标
		 * @y		点的Y坐标
		 * @xMin	矩形最小X坐标
		 * @yMin	矩形最小Y坐标
		 * @xMax	矩形最大X坐标
		 * @xMay  矩形最大Y坐标
		 */
		public static function PtInRectangle(x:Number,y:Number,xMin:Number,yMin:Number,xMax:Number,yMax:Number):Boolean
		{
			
			if(x>=xMin&&x<=xMax&&y>=yMin&&y<=yMax) 
				return true;
			else
				return false;
		}
		
		/**
		 * 线段和矩形的交点集合
		 * @p1	线的起点
		 * @p2	线的终点
		 * @xMin	矩形最小X坐标
		 * @yMin	矩形最小Y坐标
		 * @xMax	矩形最大X坐标
		 * @xMay  矩形最大Y坐标
		 **/
		public static function LineInersectRectangle(p1:Location,p2:Location,xMin:Number,yMin:Number,xMax:Number,yMax:Number):ArrayCollection
		{
			var loc:Location;
			var locArray:ArrayCollection=new ArrayCollection();
			var p3:Location,p4:Location;
			p3=new Location(xMin,yMin);
			p4=new Location(xMax,yMin);
			loc=LineInersectLine(p1,p2,p3,p4);
			if(loc!=null) locArray.addItem(loc);
			
			p3.x=xMax;p3.y=yMin;
			p4.x=xMax;p4.y=yMax;
			loc=LineInersectLine(p1,p2,p3,p4);
			if(loc!=null) locArray.addItem(loc);
			
			p3.x=xMax;p3.y=yMax;
			p4.x=xMin;p4.y=yMax;
			loc=LineInersectLine(p1,p2,p3,p4);
			if(loc!=null) locArray.addItem(loc);
			
			p3.x=xMin;p3.y=yMax;
			p4.x=xMin;p4.y=yMin;
			loc=LineInersectLine(p1,p2,p3,p4);
			if(loc!=null) locArray.addItem(loc);
			
			return locArray;
		}
		
		/**
		 * 两线段的交点(如果不交叉，返回null)
		 * @p11	线1的起点
		 * @p12	线1的终点
		 * @p21	线2的起点
		 * @p22	线2的终点
		 * @allowOutLine1 交点可否在Line1的输入的起点到终点的延长线上,默认为不可以
		 * @allowOutLine2 交点可否在Line2的输入的起点到终点的延长线上,默认为不可以
		 **/
		public static function LineInersectLine(p11:Location,p12:Location,p21:Location,p22:Location,
												allowOutLine1:Boolean=false,allowOutLine2:Boolean=false):Location
		{
			var loc:Location=null;
			var N:Number, O:Number, P:Number, Q:Number, k:Number, U:Number, V:Number;
			var tempX:Number,tempY:Number;
			var b1:Number,k1:Number,k2:Number;
			var val:Number;
			N = p12.x - p11.x;
			O = p12.y - p11.y;
			P = p22.x - p21.x;
			Q = p22.y - p21.y;
			
			k = Q * N - O * P;
			if(k==0)
				return null;
			
			U = N * p11.y - O * p11.x;
			V = P * p21.y - Q * p21.x;
			
			val=(P * U - N * V)/k;
			tempX = Number(val.toFixed(6));
			val=(Q * U - O * V) / k;
			tempY = Number(val.toFixed(6));
			
			if(!allowOutLine1)
			{
				val=lineLength(tempX,tempY,p11.x,p11.y);
				k1 = Number(val.toFixed(6));
				val=lineLength(tempX,tempY,p12.x,p12.y);
				k2 = Number(val.toFixed(6));
				val=lineLength(p11.x,p11.y,p12.x,p12.y);
				b1 = Number(val.toFixed(6));
				if(Math.abs(b1 - (k1 + k2)) > 0.00001) //注意0.001这个精度值与前面的round函数有关，如果函数取的只3位，则这里用0.01，类推
				{
					return null;
				}
			}
			if(!allowOutLine2)
			{
				val=lineLength(tempX,tempY,p21.x,p21.y);
				k1 = Number(val.toFixed(6));
				val=lineLength(tempX,tempY,p22.x,p22.y);
				k2 = Number(val.toFixed(6));
				val=lineLength(p21.x,p21.y,p22.x,p22.y);
				b1 = Number(val.toFixed(6));
				if(Math.abs(b1 - (k1 + k2)) > 0.00001) //注意0.001这个精度值与前面的round函数有关，如果函数取的只3位，则这里用0.01，类推
				{
					return null;
				}
			}
			loc=new Location(Number(tempX.toFixed(5)),Number(tempY.toFixed(5)));
			return loc;
			
			
			
		}
		/**
		 * 折线和矩形的相交部分(可能被矩形截取成多段线）
		 * @linepoints		折线所有折点
		 * @xMin	矩形最小X坐标
		 * @yMin	矩形最小Y坐标
		 * @xMax	矩形最大X坐标
		 * @xMay   矩形最大Y坐标
		 *
		 * */
		public static function PolyLineTrimByRectangle(linepoints:ArrayCollection,
													   xMin:Number,yMin:Number,xMax:Number,yMax:Number):ArrayCollection
		{
			var lineArray:ArrayCollection=new ArrayCollection();
			var polyline:PolylineGeometry=null;
			var bCuted:Boolean=false;	//是否被切断
			var bPreInRange:Boolean;
			var bCurInRange:Boolean;
			var p1:Location,p2:Location,crossPoint1:Location,crossPoint2:Location;
			var loc:PointGeometry;	  
			var point:PointGeometry=linepoints[0] as PointGeometry;
			bPreInRange=PtInRectangle(point.x,point.y,xMin,yMin,xMax,yMax);
			p1=new Location(point.x,point.y);

			
			if(bPreInRange)	//第一个点如果在矩形范围内
			{
				polyline=new PolylineGeometry();
				polyline.pointList.addItem(point);
				lineArray.addItem(polyline);
			}
			
			for(var i:int=1;i<linepoints.length;i++)
			{
				point=linepoints[i] as PointGeometry;
				bCurInRange=PtInRectangle(point.x,point.y,xMin,yMin,xMax,yMax);
				p2=new Location(point.x,point.y);

				if(bCurInRange!=bPreInRange)	//前后两个节点，一个在内部，一个不在，而必有交点
				{
					var crosspointArray:ArrayCollection=LineInersectRectangle(p1,p2,xMin,yMin,xMax,yMax);
					if(crosspointArray.length==0) 
						continue;
					crossPoint1=crosspointArray[0] as Location;
					loc=new PointGeometry();
					loc.x=crossPoint1.x;
					loc.y=crossPoint1.y;
					if(bPreInRange)
					{
						bCuted=true;
						polyline.pointList.addItem(loc);
					}
					else
					{
						bCuted=false;
						polyline=new PolylineGeometry();
						polyline.pointList.addItem(loc);
						polyline.pointList.addItem(linepoints[i]);
						lineArray.addItem(polyline);
						
					}
				}
				else
				{
					if(bCurInRange)	//两个点都在内部
					{
						polyline.pointList.addItem(linepoints[i]);
					}
					else	//两个点都不在内部，也可能有两个交点
					{
						bCuted=true;
						crosspointArray=LineInersectRectangle(p1,p2,xMin,yMin,xMax,yMax);
						if(crosspointArray.length>1)
						{
							crossPoint1=crosspointArray[0] as Location;
							crossPoint2=crosspointArray[1] as Location;
							var t1:PointGeometry=new PointGeometry();
							t1.x=crossPoint1.x;
							t1.y=crossPoint1.y;
							var t2:PointGeometry=new PointGeometry();
							t2.x=crossPoint2.x;
							t2.y=crossPoint2.y;
							polyline=new PolylineGeometry();
							polyline.pointList.addItem(t1);
							polyline.pointList.addItem(t2);
							lineArray.addItem(polyline);
						}
					}
				}
				
				p1.x=p2.x;p1.y=p2.y;
				bPreInRange=bCurInRange; 
				
			}
			return lineArray;
		}
		
		/**
		 * 返回折线的中心点和斜率
		 * @linepoints 	折线所有折点
		 * @angle			中心点的角度和线段索引
		 * */
		public static function MidPointOfPolyline(linepoints:ArrayCollection,angle:ArrayCollection):Location
		{
			var totalLength:Number=0,oneLength:Number=0,preTotal:Number=0;
			var p1:PointGeometry,p2:PointGeometry;
			var retPoint:Location=null;
			var i:int;
			var slope:Number;
			for(i=0;i<linepoints.length-1;i++)
			{
				p1=linepoints[i] as PointGeometry;
				p2=linepoints[i+1] as PointGeometry;
				totalLength+=lineLength(p1.x,p1.y,p2.x,p2.y);
			}
			totalLength=totalLength/2;
			for(i=0;i<linepoints.length-1;i++)
			{
				p1=linepoints[i] as PointGeometry;
				p2=linepoints[i+1] as PointGeometry;
				oneLength=lineLength(p1.x,p1.y,p2.x,p2.y);
				if(oneLength+preTotal>=totalLength)
				{
					retPoint=new Location(p1.x+(totalLength-preTotal)*(p2.x-p1.x)/oneLength,
						p1.y+(totalLength-preTotal)*(p2.y-p1.y)/oneLength);
					
					slope=lineSlope(p1.x,p1.y,p2.x,p2.y);
					
					if(slope==1)
						angle.addItem( -90);
					else
						angle.addItem(-1*Math.atan(slope)*180/Math.PI);
					angle.addItem(i);
					return retPoint;
				}
				preTotal+=oneLength;
			}
			
			return null; 
		}
		
		
		/**
		 * 转换折线成虚线
		 * @linepoints 折线点
		 * @star_commands 返回的虚线
		 * @star_coord 
		 * @lengthsArray 虚线样式
		 * */
		public static function ConvertToDashLine(linepoints:ArrayCollection,star_commands:Vector.<int>,star_coord:Vector.<Number>,dashModeArray:Array = null):void
		{
			var lengthsArray:Array = new Array();
			var curX:Number = 0;	// stores current x as it changes with lineTo and moveTo calls
			var curY:Number = 0;	// same as above, but for y
			var remainingDist:Number = 0;
			var startIndex:Number = 0;
			var curIndex:int = 0;	// current index in the length array, so we know which dash or gap to draw
			
			if (dashModeArray != null)
			{	// if lengths array was specified, use it
				lengthsArray = dashModeArray;
			} 
			else 
			{	// if unspecified, use a default 5-5 line
				lengthsArray = [5,5];
			}
			if (lengthsArray.length % 2 != 0){	// if array has more dashes than gaps (i.e. an odd number of values), add a 5 gap to the end
				lengthsArray.push(5);
			}
			
			if(linepoints.length>1)
			{
				star_coord.push(linepoints[0].x);
				star_coord.push(linepoints[0].y);
				star_commands.push(1);
				
				curX = linepoints[0].x;	
				curY = linepoints[0].y;
				
				// reset remainingDist and startIndex - if we are moving away from last line segment, the next one will start at the beginning of the dash-gap sequence
				remainingDist = 0;
				startIndex = 0;
				
				for(var k:int=1;k<linepoints.length;k++)
				{
					var x:Number=linepoints[k].x;
					var y:Number=linepoints[k].y;
					
					var slope:Number =(y - curY)/(x - curX);// lineSlope(curX,curY,x,y);	// get slope of segment to be drawn
					
					// record beginning x and y
					var startX:Number = curX;
					var startY:Number = curY;
					// positive or negative direction for each x and y?
					var xDir:int = (x < startX) ? -1 : 1;
					var yDir:int = (y < startY) ? -1 : 1;
					
					// keep drawing dashes and gaps as long as either the current x or y is not beyond the destination x or y
					outerLoop : 
					while (Math.abs(startX-curX) < Math.abs(startX-x) || Math.abs(startY-curY) < Math.abs(startY-y))
					{
						// loop through the array to draw the appropriate dash or gap, beginning with startIndex (either 0 or determined by the end of the last lineTo)
						for (var i:int = startIndex; i < lengthsArray.length; i++)
						{
							var dist:Number = (remainingDist == 0) ? lengthsArray[i] : remainingDist;	// distance to draw is either the dash/gap length from the array or remainingDist left over from the last lineTo if there is any
							// get increments of x and y based on distance, slope, and direction - see getCoords()
							var xInc:Number = getCoords(dist,slope).x * xDir;
							var yInc:Number = getCoords(dist,slope).y * yDir;
							// if the length of the dash or gap will not go beyond the destination x or y of the lineTo, draw the dash or gap
							if (Math.abs(startX-curX) + Math.abs(xInc) < Math.abs(startX-x) || Math.abs(startY-curY) + Math.abs(yInc) < Math.abs(startY-y))
							{
								if (i % 2 == 0)
								{	// if even index in the array, it is a dash, hence lineTo
									star_coord.push(curX + xInc);
									star_coord.push(curY + yInc);	
									star_commands.push(2);
								} 
								else 
								{	// if odd, it's a gap, so moveTo
									star_coord.push(curX + xInc);
									star_coord.push(curY + yInc);	
									star_commands.push(1);
								}
								// keep track of the new x and y
								curX += xInc;
								curY += yInc;
								curIndex = i;	// store the current dash or gap (array index)
								// reset startIndex and remainingDist, as these will only be non-zero for the first loop (through the array) of the lineTo
								startIndex = 0;
								remainingDist = 0;
							} 
							else 
							{	// if the dash or gap can't fit, break out of the loop
								remainingDist = lineLength(curX,curY,x,y);	// get the distance between the end of the last dash or gap and the destination x/y
								curIndex = i;	// store the current index
								break outerLoop;	// break out of the while loop
							}
						}
					}
					
					startIndex = curIndex;	// for next time, the start index is the last index used in the loop
					
					if (remainingDist != 0)
					{	// if there is a remaining distance, line or move from current x/y to the destination x/y
						if (curIndex % 2 == 0)
						{	// even = dash
							star_coord.push(x);
							star_coord.push(y);	
							star_commands.push(2);
							
						} 
						else 
						{	// odd = gap
							star_coord.push(x);
							star_coord.push(y);	
							star_commands.push(1);
						}
						remainingDist = lengthsArray[curIndex] - remainingDist;	// remaining distance (which will be used at the beginning of the next lineTo) is now however much is left in the current dash or gap after that final lineTo/moveTo above
					} 
					else 
					{	// if there is no remaining distance (i.e. the final dash or gap fits perfectly), we're done with the current dash or gap, so increment the start index for next time
						if (startIndex == lengthsArray.length - 1)
						{	// go to the beginning of the array if we're at the end
							startIndex = 0;
						} 
						else 
						{
							startIndex++;
						}
					}
					// at last, the current x and y are the destination x and y
					curX = x;
					curY = y;
				}
			}
		}
		
		// returns a point with the vertical and horizontal components of a diagonal given the distance and slope
		public static function getCoords(distance:Number,slope:Number):Location {
			var angle:Number = Math.atan(slope);	// get the angle from the slope
			var vertical:Number = Math.abs(Math.sin(angle)*distance);	// vertical from sine of angle and length of hypotenuse - using absolute value here and applying negative as needed in lineTo, because this number doesn't always turn out to be negative or positive exactly when I want it to (haven't thought through the math enough yet to figure out why)
			var horizontal:Number = Math.abs(Math.cos(angle)*distance);	// horizontal from cosine
			return new Location(horizontal,vertical);	// return the point			
		}
    }
}